/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package replic.console;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import replic.commons.OutputMessage;

/**
 *
 * @author Leonardo Oliveira Moreira
 */
public class RepliCConsole extends Thread {
    
    private String databaseName;
    private String replicHost;
    private int replicPort;
    private String directory;
    private String resultFile;
    private String replicConnection;
    
    private List<File> logFiles;
    
    public RepliCConsole() {
        logFiles = new ArrayList<File>();
    }

    public List<File> getLogFiles() {
        return logFiles;
    }

    public void setLogFiles(List<File> logFiles) {
        this.logFiles = logFiles;
    }
    
    public String getDirectory() {
        return directory;
    }

    public void setDirectory(String directory) {
        this.directory = directory;
    }

    public String getResultFile() {
        return resultFile;
    }

    public void setResultFile(String resultFile) {
        this.resultFile = resultFile;
    }

    public String getReplicHost() {
        return replicHost;
    }

    public void setReplicHost(String replicHost) {
        this.replicHost = replicHost;
    }

    public int getReplicPort() {
        return replicPort;
    }

    public void setReplicPort(int replicPort) {
        this.replicPort = replicPort;
    }
    
    public String getDatabaseName() {
        return databaseName;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }

    public String getReplicConnection() {
        return replicConnection;
    }

    public void setReplicConnection(String replicConnection) {
        this.replicConnection = replicConnection;
    }
    
    @Override
    public void run() {
        OutputMessage.println("### RepliC Console is Starting");
        
        List<RepliCTerminal> terminalList = new ArrayList<RepliCTerminal>();
        
        int terminalId = 0;
        
        for (File f : logFiles) {
            OutputMessage.println("Creating a new RepliC Terminal");
            if (replicConnection.equalsIgnoreCase("socket")) {
                terminalList.add(new RepliCTerminalSocket(++terminalId, f, databaseName, replicHost, replicPort));
            }
            if (replicConnection.equalsIgnoreCase("driver")) {
                terminalList.add(new RepliCTerminalDriver(++terminalId, f, databaseName, replicHost, replicPort));
            }
            OutputMessage.println("RepliC Terminal Created with ID = " + terminalId);
        }
        
        OutputMessage.println(terminalList.size() + " RepliC Terminal(s) created");
        
        long startExperimentTime = System.currentTimeMillis();
        
        for (RepliCTerminal terminal : terminalList) {
            terminal.start();
        }
        
        boolean finished = false;
        while (!finished) {
            finished = true;
            for (RepliCTerminal terminal : terminalList) {
                if (terminal.isExecuting()) {
                    finished = false;
                }
            }
        }
        
        long endExperimentTime = System.currentTimeMillis();
        
        OutputMessage.println("### The execution lasted " + (endExperimentTime - startExperimentTime) + " millisecond(s) | " + ((endExperimentTime - startExperimentTime) / 1000) + " second(s)");
        OutputMessage.println("### Console is Ending");
        OutputMessage.println("### Generating Result File Log...");
        
        List<TransactionResult> transactionBuffer = new ArrayList<TransactionResult>();
        
        for (RepliCTerminal terminal : terminalList) {
            transactionBuffer.addAll(terminal.getTransactionResults());
        }
        
        try {
            PrintWriter writer = new PrintWriter(new File(resultFile));
            writer.println("### RepliC Console v.0.1");
            writer.println("### PARAMETERS");
            writer.println("Terminal(s)....: " + terminalList.size());
            writer.println("Transaction(s).: " + transactionBuffer.size());
            writer.println("Duration.......:" + (endExperimentTime - startExperimentTime) + " millisecond(s) | " + ((endExperimentTime - startExperimentTime) / 1000) + " second(s)");
            writer.println("### BODY");
            writer.println("start_time (s)" + ";" + "end_time (s)" + ";" + "transaction_count");
            long startTime = startExperimentTime;
            while (transactionBuffer.size() > 0) {
                long endTime = startTime + 5000;
                long count = 0;
                for (int i = 0; i < transactionBuffer.size(); i++) {
                    TransactionResult tr = transactionBuffer.get(i);
                    if (tr.getEndTime() <= endTime) {
                        transactionBuffer.remove(i);
                        count++;
                        i--;
                    }
                }
                
                writer.println(((startTime- startExperimentTime) / 1000) + ";" + ((((endTime - startExperimentTime) / 1000) < ((endExperimentTime - startExperimentTime) / 1000)) ? ((endTime - startExperimentTime) / 1000) : ((endExperimentTime - startExperimentTime) / 1000)) + ";" + count);
                startTime = endTime;
            }

            writer.close();
            writer.println("### END");
        } catch (FileNotFoundException ex) {
            OutputMessage.println("ERROR: " + ex.getMessage());
        }
        
        OutputMessage.println("### Result File Log Generated");
        OutputMessage.println("### Console Ended");
    }

    public static void main(String[] args) {
        OutputMessage.println("### RepliC Console v.0.1");
        if (args == null || args.length != 6) {
            OutputMessage.println("Command Sintax......: java -jar replic-console.jar <spy log files directory> <result file> <database_name> <replic_host> <replic_port> <driver|socket>");
            OutputMessage.println("Command Example.....: java -jar replic-console.jar /home/user/spy-logs /home/user/result.log tpcc 192.168.0.1 7777 driver");
        }
        else {
            String directory        = args[0];
            String resultFile       = args[1];
            String databaseName     = args[2];
            String replicHost       = args[3];
            String replicPort       = args[4];
            String replicConnection = args[5];
            
            RepliCConsole console = new RepliCConsole();

            OutputMessage.println("### Parameters Loaded");
            OutputMessage.println("Log Files Directory.: " + directory);
            File d = new File(directory);
            if (d == null || !d.exists() || !d.isDirectory()) {
                OutputMessage.println("ERROR: " + directory + " is not a valid directory or not exists");
                System.exit(0);
            }
            else {
                File[] logList = d.listFiles();
                for (File f : logList) {
                    if (!f.isDirectory() && f.getAbsolutePath().endsWith(".log")) {
                        console.getLogFiles().add(f);
                        OutputMessage.println(f.getAbsolutePath() + " loaded");
                    }
                    else {
                        OutputMessage.println("ERROR: " + f.getAbsolutePath() + " is not a valid log file");
                        System.exit(0);
                    }
                }
            }
            OutputMessage.println("Result File.........: " + resultFile);
            File r = new File(resultFile);
            try {
                if (r.exists()) {
                    OutputMessage.println("ERROR: " + resultFile + " file already exists");
                    System.exit(0);
                }
                if (!r.createNewFile()) {
                    OutputMessage.println("ERROR: " + "Can not create " + resultFile);
                    System.exit(0);
                }
            } catch (IOException ex) {
                OutputMessage.println("ERROR: " + ex.getMessage());
                System.exit(0);
            }
            OutputMessage.println(resultFile + " created");
            OutputMessage.println("Database............: " + databaseName);
            OutputMessage.println("RepliC Host.........: " + replicHost);
            OutputMessage.println("RepliC Port.........: " + replicPort);
            if (!replicConnection.equalsIgnoreCase("driver") && !replicConnection.equalsIgnoreCase("socket")) {
                OutputMessage.println("ERROR: " + "Invalid connection method: " + replicConnection);
                System.exit(0);
            }
            OutputMessage.println("RepliC Connection...: " + replicConnection);
            
            console.setDatabaseName(databaseName);
            console.setDirectory(directory);
            console.setResultFile(resultFile);
            console.setReplicHost(replicHost);
            console.setReplicPort(Integer.parseInt(replicPort));
            console.setReplicConnection(replicConnection);
            
            OutputMessage.println("### Console Started");
            
            console.run();
        }
    }
}
